package net.esj.basic.dao.hibernate.impl;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.esj.basic.dao.QueryMapDao;
import net.esj.basic.dao.hibernate.HibernateSessionLocale;
import net.esj.basic.utils.Pagination;
import net.esj.basic.utils.SQLUtils;

import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@Deprecated
public class HibernateQueryMapDaoImpl implements
		QueryMapDao {

	private HibernateSessionLocale hibernateSessionLocale;
	
	@Autowired
	public void setHibernateSessionLocale(
			HibernateSessionLocale hibernateSessionLocale) {
		this.hibernateSessionLocale = hibernateSessionLocale;
	}
	
	@Override
	public int queryCountByMap(Map<String, Object> query, Class<?> tclass) {
		Criteria pagecriteria = getSession().createCriteria(tclass);
		for (Map.Entry<String, Object> entry : query.entrySet()) {
			createSubCriteria(pagecriteria, entry.getKey(), entry.getValue());
			genQueryStatment(pagecriteria,entry.getKey(), entry.getValue());
		}
		pagecriteria.setProjection(Projections.count("id"));
		List counts = pagecriteria.list();
		Iterator iterator = counts.iterator();
		int sum = 0;
		while (iterator.hasNext()) {
			sum = Integer.valueOf( iterator.next().toString());
		}
		return sum;
	}

	@Override
	public List queryListByMap(Map<String, Object> query, Class<?> tclass) {

		Criteria criteria = getSession().createCriteria(tclass);
		
		for (Map.Entry<String, Object> entry : query.entrySet()) {
			createSubCriteria(criteria, entry.getKey(), entry.getValue());
			genQueryStatment(criteria,entry.getKey(), entry.getValue());
			
		}
		return criteria.list();
	}

	@Override
	public <T> Pagination<T> queryPageByMap(Pagination<T> page, Class<T> tclass) {

		Criteria criteria = getSession().createCriteria(tclass);
		Criteria pagecriteria = getSession().createCriteria(tclass);
		
		for (Map.Entry<String, Object> entry : page.getQuery().entrySet()) {
			createSubCriteria(criteria, entry.getKey(), entry.getValue());
			createSubCriteria(pagecriteria, entry.getKey(), entry.getValue());
			genQueryStatment(criteria,entry.getKey(), entry.getValue());
			genQueryStatment(pagecriteria, entry.getKey(), entry.getValue());
			
		}
		try {
			queryCount(pagecriteria, page);
			criteria.setMaxResults(page.getRp());
			criteria.setFirstResult((page.getPage() - 1) * page.getRp());
			List list = criteria.list();
			page.setRows(list);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return page;
	}

	@Override
	public List queryTopByMap(Map<String, Object> query, Class<?> tclass,
			int count) {
		Criteria criteria = getSession().createCriteria(tclass);
		
		for (Map.Entry<String, Object> entry : query.entrySet()) {
			createSubCriteria(criteria, entry.getKey(), entry.getValue());
			genQueryStatment(criteria,entry.getKey(), entry.getValue());
			
		}
		criteria.setMaxResults(count);
		return criteria.list();
	}

	private void createSubCriteria(Criteria parent,String key,Object value){
		Criteria c = null;
		if(key.split("\\.").length>1){
			String tclazz = key.substring(0, key.indexOf('.'));
			key = key.substring(key.indexOf('.')+1, key.length());
			if("this".equals(parent.getAlias())){
				c = parent.createCriteria(tclazz, tclazz);
			}else{
				c = parent.createCriteria(tclazz, parent.getAlias()+"."+tclazz);
			}
			createSubCriteria(c, key, value);
		}
	}
	
	private void genQueryStatment(Criteria criteria, String key, Object value) {
		key = key.replace('#', '.');
		String[] tmps = key.split("_");
		if (tmps.length != 2) {
			criteria.add(Restrictions.eq(tmps[0], value));
			return;
		}
		if (SQLUtils.SQL_STATE_EQUAL.equals(tmps[1])) {
			criteria.add(Restrictions.eq(tmps[0], value));
		} else if (SQLUtils.SQL_STATE_GRATER.equals(tmps[1])) {
			criteria.add(Restrictions.gt(tmps[0], value));
		} else if (SQLUtils.SQL_STATE_GRATER_AND_EQUAL.equals(tmps[1])) {
			criteria.add(Restrictions.ge(tmps[0], value));
		} else if (SQLUtils.SQL_STATE_LESS.equals(tmps[1])) {
			criteria.add(Restrictions.lt(tmps[0], value));
		} else if (SQLUtils.SQL_STATE_LESS_AND_EQUAL.equals(tmps[1])) {
			criteria.add(Restrictions.le(tmps[0], value));
		} else if (SQLUtils.SQL_STATE_LIKE.equals(tmps[1])) {
			criteria.add(Restrictions.like(tmps[0], value));
		} else if (SQLUtils.SQL_STATE_NOT.equals(tmps[1])) {
			criteria.add(Restrictions.ne(tmps[0], value));
		} else if (SQLUtils.SQL_STATE_ORDERBY.equals(tmps[1])) {// name_order
																// value: asc
			if (SQLUtils.SQL_STATE_ORDER_ASC.equals(value)) {
				criteria.addOrder(Order.asc(tmps[0]));
			} else if (SQLUtils.SQL_STATE_ORDER_DESC.equals(value)) {
				criteria.addOrder(Order.desc(tmps[0]));
			}
		} else if (SQLUtils.SQL_STATE_GROUPBY.equals(tmps[1])) {
			criteria.setProjection(Projections.groupProperty(tmps[0]));
		} else if (SQLUtils.SQL_STATE_FETCH.equals(tmps[0])) {
			if (SQLUtils.HQL_FETCH_JOIN.equals(value)) {
				criteria.setFetchMode(tmps[1], FetchMode.JOIN);// fetch_group
																// value: join
			} else if (SQLUtils.HQL_FETCH_EAGER.equals(value)) {
				criteria.setFetchMode(tmps[1], FetchMode.EAGER);// fetch_group
																// value: join
			} else if (SQLUtils.HQL_FETCH_LAZY.equals(value)) {
				criteria.setFetchMode(tmps[1], FetchMode.LAZY);// fetch_group
																// value: join
			} else if (SQLUtils.HQL_FETCH_SELECT.equals(value)) {
				criteria.setFetchMode(tmps[1], FetchMode.SELECT);// fetch_group
																	// value:
																	// join
			} else {
				criteria.setFetchMode(tmps[1], FetchMode.DEFAULT);// fetch_group
																	// value:
																	// join
			}
		} else if(SQLUtils.SQL_STATE_IN.equals(tmps[1])){
			if(value.getClass().isArray()&& ((Object[]) value).length>0){
				criteria.add(Restrictions.in(tmps[0], (Object[]) value));
			}
		}else {
			criteria.add(Restrictions.eq(tmps[0], value));
		}
	}
	
	protected void queryCount(Criteria criteria, Pagination page) {
		criteria.setProjection(Projections.count("id"));
		List counts = criteria.list();
		Iterator iterator = counts.iterator();
		int sum = 0;
		while (iterator.hasNext()) {
			sum = Integer.valueOf( iterator.next().toString());
		}
		//总数量
		page.setTotal(sum);
		//总页数
		page.setSum((sum-1)/page.getRp()+1);
	}
	
	protected final Session getSession(){
		return hibernateSessionLocale.getCurrentSession();
	}
}
